package com.apes.fn.rpt.profit.grossProfitProcess;

import com.alibaba.fastjson.JSONObject;
import com.apes.fn.rpt.profit.GrossProfit;
import com.apes.fn.rpt.profit.GrossProfitDao;
import com.apes.fn.rpt.profit.GrossProfitRepository;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.util.Arith;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import org.hibernate.query.internal.NativeQueryImpl;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.*;
import java.util.function.Function;

/**
 * 公共处理器
 */
public abstract class CommonGrossProfitProcess implements GrossProfitProcess {

    @Autowired
    private EntityManager entityManager;
    @Autowired
    private GrossProfitRepository grossProfitRepository;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private DeptRepository deptRepository;


    @Override
    public void execute(Date taskDate, Function<String, String> function) {
        // 第一步：获取数据集
        String sql = getSQL(taskDate);
        String packSql = function.apply(sql);
        Query query = entityManager.createNativeQuery(packSql.toString());
        query.setParameter("P_DATE", DateUtil.format(taskDate, DateUtil.SHOW_DATE_FORMAT));
        query.unwrap(NativeQueryImpl.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        List<Map> grossProfitItems = query.getResultList();
        // 第二步：执行写入操作
        grossProfitItems.forEach(this::saveGrossProfit);


    }

    @Override
    public abstract String getSQL(Date taskDate);

    @Override
    public void changeType(Integer typeNumber){
        throw new RuntimeException("未定义变更类型");
    }

    /**
     * 绘制毛利报表
     *
     * @param map grossProfitItem
     */
    public void saveGrossProfit(Map map) {
        JSONObject grossProfitItem = new JSONObject(map);
        GrossProfit grossProfit = grossProfitRepository.findOne(JpaDsl.toCriteriaByEq("statisticsDate", grossProfitItem.getDate("CREATE_DATE"),
                "dept.id", grossProfitItem.getString("DEPT_ID"), "type", grossProfitItem.getString("SERVE_TYPE_NAME"), "incomeCategories",
                grossProfitItem.getString("INCOME_CATEGORIES"))).orElse(new GrossProfit());

        grossProfit.setCompany(partyRoleRepository.findOne(grossProfitItem.getString("COMPANY_ID")));
        grossProfit.setDept(deptRepository.findOne(grossProfitItem.getString("DEPT_ID")));
        grossProfit.setType(grossProfitItem.getString("SERVE_TYPE_NAME"));
        grossProfit.setTimes(grossProfitItem.getDoubleValue("TIMES"));
        grossProfit.setIncomeCategories(grossProfitItem.getString("INCOME_CATEGORIES"));
        grossProfit.setAmtSale(grossProfitItem.getDoubleValue("AMOUNT"));
        grossProfit.setUnBillAmount(Arith.sub(grossProfitItem.getDoubleValue("AMOUNT"), grossProfitItem.getDoubleValue("PRICE_TOTAL")));
        grossProfit.setBillAmount(grossProfitItem.getDoubleValue("PRICE_TOTAL"));
        grossProfit.setAmtCost(grossProfitItem.getDoubleValue("COST"));
        grossProfit.setAmtMaterialCost(grossProfitItem.getDoubleValue("CONSUMABLE_USE"));
        grossProfit.setAccessoryCost(grossProfitItem.getDoubleValue("ACCESSORY_COST"));
        grossProfit.setManHourCost(grossProfitItem.getDoubleValue("MAN_HOUR_COST"));
        grossProfit.setSupplyChainManagementFee(grossProfitItem.getDoubleValue("SUPPLY_CHAIN_MANAGEMENT_FEE"));
        grossProfit.setPlatformManagementFee(grossProfitItem.getDoubleValue("PLATFORM_MANAGEMENT_FEE"));
        grossProfit.setAmtProfit(grossProfitItem.getDoubleValue("GROSS_PROFIT"));
        grossProfit.setProfitRate(grossProfitItem.getDoubleValue("GROSS_RATE"));
        grossProfit.setStatisticsDate(grossProfitItem.getDate("CREATE_DATE"));
        grossProfit.setCrossCompanyIncome(grossProfitItem.get("VIP_IN")==null?0:grossProfitItem.getDoubleValue("VIP_IN"));
        grossProfit.setCrossCompanyPay(grossProfitItem.get("VIP_OUT")==null?0:grossProfitItem.getDoubleValue("VIP_OUT"));
        grossProfitRepository.saveAndFlush(grossProfit);
    }

}
